﻿namespace FFF.Test.Controllers
{
    using System;
    using System.IO;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using Senparc.CO2NET.Cache;
    using Senparc.CO2NET.Extensions;
    using Senparc.CO2NET.HttpUtility;
    using Senparc.Weixin.TenPay.V3;
    using Senparc.Weixin.WxOpen.AdvancedAPIs.Sns;
    using Senparc.Weixin.WxOpen.Containers;
    using Senparc.Weixin.WxOpen.Entities;
    using Senparc.Weixin.WxOpen.Entities.Request;
    using Senparc.Weixin.WxOpen.Helpers;
    using Senparc.Weixin;
    using Senparc.Weixin.MP;
    using FFF.Test.Util.Web;
    using Microsoft.AspNetCore.Authorization;

    /// <summary>
    /// 微信小程序Controller
    /// </summary>
    public partial class WxOpenController : YdmAbpControllerBase
    {
        private static readonly string Token = Config.SenparcWeixinSetting.WxOpenToken; // 与微信小程序后台的Token设置保持一致，区分大小写。
        private static readonly string EncodingAESKey = Config.SenparcWeixinSetting.WxOpenEncodingAESKey; //与微信小程序后台的EncodingAESKey设置保持一致，区分大小写。
        private static readonly string WxOpenAppId = Config.SenparcWeixinSetting.WxOpenAppId; // 与微信小程序后台的AppId设置保持一致，区分大小写。
        private static readonly string WxOpenAppSecret = Config.SenparcWeixinSetting.WxOpenAppSecret; // 与微信小程序账号后台的AppId设置保持一致，区分大小写。

        private readonly Func<string> _getRandomFileName = () => DateTime.Now.ToString("yyyyMMdd-HHmmss") + Guid.NewGuid().ToString("n").Substring(0, 6);

        /// <summary>
        /// GET请求用于处理微信小程序后台的URL验证
        /// </summary>
        /// <param name="postModel">微信传的model</param>
        /// <param name="echostr">随机字符</param>
        /// <returns>actionresult</returns>
        [HttpGet]
        [ActionName("Index")]
        [AllowAnonymous]
        public ActionResult Get(PostModel postModel, string echostr)
        {
            if (CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel.Nonce, Token))
            {
                return base.Content(echostr); // 返回随机字符串则表示验证通过
            }
            else
            {
                return base.Content("failed:" + postModel.Signature + "," + CheckSignature.GetSignature(postModel.Timestamp, postModel.Nonce, Token) + "。" +
                    "如果你在浏览器中看到这句话，说明此地址可以被作为微信小程序后台的Url，请注意保持Token一致。");
            }
        }

        ///// <summary>
        ///// 用户发送消息后，微信平台自动Post一个请求到这里，并等待响应XML。
        ///// </summary>
        //[HttpPost]
        //[ActionName("Index")]
        //public ActionResult Post(PostModel postModel)
        //{
        //    if (!CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel.Nonce, Token))
        //    {
        //        return Content("参数错误！");
        //    }

        //    postModel.Token = Token;//根据自己后台的设置保持一致
        //    postModel.EncodingAESKey = EncodingAESKey;//根据自己后台的设置保持一致
        //    postModel.AppId = WxOpenAppId;//根据自己后台的设置保持一致（必须提供）

        //    //v4.2.2之后的版本，可以设置每个人上下文消息储存的最大数量，防止内存占用过多，如果该参数小于等于0，则不限制
        //    int maxRecordCount = 10;

        //    string logPath = Server.GetMapPath(string.Format("~/App_Data/WxOpen/{0}/", DateTime.Now.ToString("yyyy-MM-dd")));
        //    if (!Directory.Exists(logPath))
        //    {
        //        Directory.CreateDirectory(logPath);
        //    }

        //    //自定义MessageHandler，对微信请求的详细判断操作都在这里面。
        //    CustomWxOpenMessageHandler messageHandler = new CustomWxOpenMessageHandler(Request.GetRequestMemoryStream(), postModel, maxRecordCount);

        //    try
        //    {

        //        /* 如果需要添加消息去重功能，只需打开OmitRepeatedMessage功能，SDK会自动处理。
        //         * 收到重复消息通常是因为微信服务器没有及时收到响应，会持续发送2-5条不等的相同内容的RequestMessage*/
        //        messageHandler.OmitRepeatedMessage = true;

        //        //测试时可开启此记录，帮助跟踪数据，使用前请确保App_Data文件夹存在，且有读写权限。
        //        messageHandler.SaveRequestMessageLog();//记录 Request 日志（可选）

        //        messageHandler.Execute();//执行微信处理过程（关键）

        //        messageHandler.SaveResponseMessageLog();//记录 Response 日志（可选）

        //        //return Content(messageHandler.ResponseDocument.ToString());//v0.7-
        //        return new FixWeixinBugWeixinResult(messageHandler);//为了解决官方微信5.0软件换行bug暂时添加的方法，平时用下面一个方法即可
        //                                                            //return new WeixinResult(messageHandler);//v0.8+
        //    }
        //    catch (Exception ex)
        //    {
        //        using (TextWriter tw = new StreamWriter(Server.GetMapPath("~/App_Data/Error_WxOpen_" + _getRandomFileName() + ".txt")))
        //        {
        //            tw.WriteLine("ExecptionMessage:" + ex.Message);
        //            tw.WriteLine(ex.Source);
        //            tw.WriteLine(ex.StackTrace);
        //            //tw.WriteLine("InnerExecptionMessage:" + ex.InnerException.Message);

        //            if (messageHandler.ResponseDocument != null)
        //            {
        //                tw.WriteLine(messageHandler.ResponseDocument.ToString());
        //            }

        //            if (ex.InnerException != null)
        //            {
        //                tw.WriteLine("========= InnerException =========");
        //                tw.WriteLine(ex.InnerException.Message);
        //                tw.WriteLine(ex.InnerException.Source);
        //                tw.WriteLine(ex.InnerException.StackTrace);
        //            }

        //            tw.Flush();
        //            tw.Close();
        //        }

        //        return Content(string.Empty);
        //    }
        //}

        //[HttpPost]
        //public ActionResult RequestData(string nickName)
        //{
        //    var data = new
        //    {
        //        msg = string.Format("服务器时间：{0}，昵称：{1}", DateTime.Now, nickName)
        //    };
        //    return base.Json(data);
        //}

        /// <summary>
        /// wx.login登陆成功之后发送的请求
        /// </summary>
        /// <param name="code">用户登陆Code</param>
        /// <returns>登陆信息</returns>
        [HttpPost]
        [AllowAnonymous]
        public ActionResult OnLogin(string code)
        {
            JsCode2JsonResult jsonResult = SnsApi.JsCode2Json(WxOpenAppId, WxOpenAppSecret, code);
            if (jsonResult.errcode == ReturnCode.请求成功)
            {
                //Session["WxOpenUser"] = jsonResult;//使用Session保存登陆信息（不推荐）
                //使用SessionContainer管理登录信息（推荐）
                string unionId = string.Empty;
                SessionBag sessionBag = SessionContainer.UpdateSession(null, jsonResult.openid, jsonResult.session_key, unionId);

                //注意：生产环境下SessionKey属于敏感信息，不能进行传输！
                return base.Json(new { success = true, msg = "OK", sessionId = sessionBag.Key, sessionKey = sessionBag.SessionKey });
            }
            else
            {
                return base.Json(new { success = false, msg = jsonResult.errmsg });
            }
        }

        /// <summary>
        /// 检查域名
        /// </summary>
        /// <param name="sessionId">用户sessionId</param>
        /// <param name="rawData">元数据</param>
        /// <param name="signature">签名</param>
        /// <returns>签名信息</returns>
        [HttpPost]
        [AllowAnonymous]
        public ActionResult CheckWxOpenSignature(string sessionId, string rawData, string signature)
        {
            try
            {
                bool checkSuccess = EncryptHelper.CheckSignature(sessionId, rawData, signature);
                return base.Json(new { success = checkSuccess, msg = checkSuccess ? "签名校验成功" : "签名校验失败" });
            }
            catch (Exception ex)
            {
                return base.Json(new { success = false, msg = ex.Message });
            }
        }

        //[HttpPost]
        //public ActionResult DecodeEncryptedData(string type, string sessionId, string encryptedData, string iv)
        //{
        //    DecodeEntityBase decodedEntity = null;
        //    switch (type.ToUpper())
        //    {
        //        case "USERINFO": //wx.getUserInfo()
        //            decodedEntity = Senparc.Weixin.WxOpen.Helpers.EncryptHelper.DecodeUserInfoBySessionId(
        //                sessionId,
        //                encryptedData, iv);
        //            break;
        //        default:
        //            break;
        //    }

        //    //检验水印
        //    bool checkWartmark = false;
        //    if (decodedEntity != null)
        //    {
        //        checkWartmark = decodedEntity.CheckWatermark(WxOpenAppId);
        //    }

        //    //注意：此处仅为演示，敏感信息请勿传递到客户端！
        //    return base.Json(new
        //    {
        //        success = checkWartmark,
        //        //decodedEntity = decodedEntity,
        //        msg = string.Format("水印验证：{0}",
        //                checkWartmark ? "通过" : "不通过")
        //    });
        //}

        //[HttpPost]
        //public ActionResult TemplateTest(string sessionId, string formId)
        //{
        //    TemplateMessageService templateMessageService = new TemplateMessageService();
        //    try
        //    {
        //        SessionBag sessionBag = templateMessageService.RunTemplateTest(WxOpenAppId, sessionId, formId);

        //        return Json(new { success = true, msg = "发送成功，请返回消息列表中的【服务通知】查看模板消息。\r\n点击模板消息还可重新回到小程序内。" });
        //    }
        //    catch (Exception ex)
        //    {
        //        SessionBag sessionBag = SessionContainer.GetSession(sessionId);
        //        string openId = sessionBag != null ? sessionBag.OpenId : "用户未正确登陆";

        //        return Json(new { success = false, openId = openId, formId = formId, msg = ex.Message });
        //    }
        //}

        /// <summary>
        /// 解密电话号码
        /// </summary>
        /// <param name="sessionId">sessionId</param>
        /// <param name="encryptedData">加密的数据</param>
        /// <param name="iv">iv数据</param>
        /// <returns>手机解密数据</returns>
        public ActionResult DecryptPhoneNumber(string sessionId, string encryptedData, string iv)
        {
            SessionBag sessionBag = SessionContainer.GetSession(sessionId);
            try
            {
                DecodedPhoneNumber phoneNumber = EncryptHelper.DecryptPhoneNumber(sessionId, encryptedData, iv);

                //throw new WeixinException("解密PhoneNumber异常测试");//启用这一句，查看客户端返回的异常信息

                return base.Json(new { success = true, phoneNumber = phoneNumber });
            }
            catch (Exception ex)
            {
                return base.Json(new { success = false, msg = ex.Message });

            }
        }

        //public ActionResult GetPrepayid(string sessionId)
        //{
        //    try
        //    {
        //        SessionBag sessionBag = SessionContainer.GetSession(sessionId);
        //        string openId = sessionBag.OpenId;

        //        //生成订单10位序列号，此处用时间和随机数生成，商户根据自己调整，保证唯一
        //        string sp_billno = string.Format("{0}{1}{2}", Config.SenparcWeixinSetting.TenPayV3_MchId /*10位*/, DateTime.Now.ToString("yyyyMMddHHmmss"),
        //                TenPayV3Util.BuildRandomStr(6));

        //        string timeStamp = TenPayV3Util.GetTimestamp();
        //        string nonceStr = TenPayV3Util.GetNoncestr();

        //        string body = "小程序微信支付Demo";
        //        int price = 1;//单位：分
        //        TenPayV3UnifiedorderRequestData xmlDataInfo = new TenPayV3UnifiedorderRequestData(WxOpenAppId, Config.SenparcWeixinSetting.TenPayV3_MchId, body, sp_billno,
        //            price, HttpContext.UserHostAddress().ToString(), Config.SenparcWeixinSetting.TenPayV3_WxOpenTenpayNotify, TenPay.TenPayV3Type.JSAPI, openId, Config.SenparcWeixinSetting.TenPayV3_Key, nonceStr);

        //        UnifiedorderResult result = TenPayV3.Unifiedorder(xmlDataInfo);//调用统一订单接口

        //        WeixinTrace.SendCustomLog("统一订单接口调用结束", "请求：" + xmlDataInfo.ToJson() + "\r\n\r\n返回结果：" + result.ToJson());

        //        string packageStr = "prepay_id=" + result.prepay_id;

        //        //记录到缓存

        //        IBaseObjectCacheStrategy cacheStrategy = CacheStrategyFactory.GetObjectCacheStrategyInstance();
        //        cacheStrategy.Set($"WxOpenUnifiedorderRequestData-{openId}", xmlDataInfo, TimeSpan.FromDays(4));//3天内可以发送模板消息
        //        cacheStrategy.Set($"WxOpenUnifiedorderResultData-{openId}", result, TimeSpan.FromDays(4));//3天内可以发送模板消息

        //        return base.Json(new
        //        {
        //            success = true,
        //            prepay_id = result.prepay_id,
        //            appId = Config.SenparcWeixinSetting.WxOpenAppId,
        //            timeStamp,
        //            nonceStr,
        //            package = packageStr,

        //            //signType = "MD5",
        //            paySign = TenPayV3.GetJsPaySign(WxOpenAppId, timeStamp, nonceStr, packageStr, Config.SenparcWeixinSetting.TenPayV3_Key)
        //        });
        //    }
        //    catch (Exception ex)
        //    {
        //        return base.Json(new
        //        {
        //            success = false,
        //            msg = ex.Message
        //        });
        //    }

        //}
    }
}
